package SSF.OS.NetFlow.Util;

import SSF.OS.*;
import SSF.Net.*;
import SSF.Util.Streams.*;
import SSF.OS.NetFlow.*;
import SSF.Net.Util.*;
import com.renesys.raceway.DML.*;
import java.util.*;

/**
 * map the networks after everything is inited.
 */
public class MapMonitor implements ProtocolMonitor
{
    public static String STREAM_TYPE="SSFNet_Map";

    IP ipSess = null;

    public void receive(ProtocolMessage packet, ProtocolSession fromSession,
			ProtocolSession toSession)
    {
	//does nothing in receive
    }

    public void config(ProtocolSession ownerProtocol, Configuration cfg) throws configException
    {
	ipSess = (IP)ownerProtocol;
	//nothing else is needed here either
    }

    public void init()
    {
	ProbeSession theProbe = null;
	try {
	    theProbe = 
		(ProbeSession)(ipSess.inGraph().SessionForName("probe"));
	}
	catch (ProtocolException pe) {
	    System.err.println("Error when init MapMonitor");
	    System.err.println(pe.getMessage());
	    System.exit(1);
	}

	StreamInterface theStream = theProbe.getRecorder(); 

	int hostCode = theProbe.getHostCode();  // uses the NHI address 

	int dataTypeCode = theStream.getRecordTypeCode(STREAM_TYPE);

	// dump the nhi, ip, peer-ip for each NIC

	int nicCount = ipSess.INTERFACE_COUNT;
	byte[] bytes =null;
	for (int i=0; i<nicCount; i++) {
	    //make data
	    bytes = generateData(ipSess, i);

	    if (bytes != null) {
		//for debug
		System.out.println(bytes.length);

		theStream.send(dataTypeCode, hostCode,
			       0, bytes, 0, bytes.length);
	    }
	}
    }

    protected byte[] generateData(IP ipSession, int nicNum)
    {
	String nhi = null;

	nhi = ((Host)(ipSession.inGraph())).nhi+"("+ipSession.INTERFACE_SET[nicNum].ID + ")";


	//construct peer IP vector.
	Vector peerVec = new Vector();
	int peer_count = 0;

	if (ipSession.INTERFACE_SET[nicNum].link_hw == null)
	    return null;    //not connected??
	for (Enumeration enum = ipSession.INTERFACE_SET[nicNum].link_hw.peers
		 (ipSession.INTERFACE_SET[nicNum]); enum.hasMoreElements();) {
	    peer_count++;
	    peerVec.add(new Integer(((NIC)enum.nextElement()).ipAddr));
	}

	//create a byte array. 
	//"1" is the length of nhi, should < 255.
	//"8" is the length of the ip of itself.
	//    plus the length of the count of peers
	byte[] bytes = new byte[nhi.length() + 1 + 8 + 4*peer_count];

	int currentIndex = BytesUtil.intToBytes(ipSession.INTERFACE_SET[nicNum].ipAddr, bytes, 0);

	//for debug
	System.out.println(nhi+" "+IP_s.IPtoString(ipSession.INTERFACE_SET[nicNum].ipAddr)+ " "+ peer_count+" "+bytes.length);
	currentIndex = BytesUtil.stringToBytes(nhi, bytes, currentIndex);
	currentIndex = BytesUtil.intToBytes(peer_count, bytes, currentIndex);
	for (int i=0; i<peer_count; i++) {
	    currentIndex = BytesUtil.intToBytes(((Integer)peerVec.get(i)).intValue(), bytes, currentIndex);

	    //for debug
	    System.out.println(IP_s.IPtoString(((Integer)peerVec.get(i)).intValue()));
	}


	//for debug
	//	for (int j=0; j<bytes.length; j++) {
	//  System.out.println(bytes[j]);
	//}

	return bytes;
    }
}
